

#include <iostream>
#include <map>
#include <string>
#include <vector>

#include <climits>
#include <sstream>

#include <fstream>

#include "WellSizedVector.h"
#include "PositionVector.h"

#include "MapsDisk.h"

using namespace std;



void MapsDisk::writeSuperMap(map<unsigned long long, WellSizedVector> & wordDictionary){
	
	string file_name = "/work/superMaps/SuperMapsFile_";
	file_name += intToStr(miniMapsInfo.miniMapCouter);
	
	ofstream miniMapsFile(file_name.c_str());
	miniMapsInfo.miniMapCouter++;

	map<unsigned long long, WellSizedVector>::iterator it;
	
//		for (it = myFriendAurelio.wordDictionary.begin(); it != myFriendAurelio.wordDictionary.end(); it++) {
//			cout << "Palavra Hash: " << it->first << endl;
//			cout << "Quantidade: " << (it->second).getVectorSize() << endl;
//			cout << "Presente nos documentos: " << (it->second).listDocs() << endl;
//			cout << endl;
//		}	
	string infoLine;
//		cout << "wordDictionary: " << endl;
//		cout << "Size: " << myFriendAurelio.wordDictionary.size() << endl;
	for (it = wordDictionary.begin(); it != wordDictionary.end(); it++) {
		// unsigned long long
//			cout << "\t ID: " << it->first << endl;
		infoLine += intToStr( it->first ) + ":";
		// WellSizedVector
//			cout << "\t vectorIndex: " << (it->second).vectorIndex << endl;
		infoLine += intToStr(( it->second).vectorIndex ) + ":";
//			cout << "\t documents Size: " << (it->second).documents.size() << endl;
		infoLine += intToStr( (it->second).documents.size() ) + ":";
		
		// PositionVector
		vector<PositionVector>::iterator itt;
		for(itt = (it->second).documents.begin(); itt != (it->second).documents.end(); itt++){
//				cout << "\t\t PositionVector id: " << itt->id << endl;
			infoLine += intToStr( itt->id ) + ":";
//				cout << "\t\t PositionVector firstOccurrence: " << itt->firstOccurrence << endl;
			infoLine += intToStr( itt->firstOccurrence ) + ":";
//				cout << "\t\t position Size(): " << itt->positions.size() << endl;
			infoLine += intToStr( itt->positions.size() ) + ":";
			
			vector<unsigned short>::iterator ittt;
			for(ittt = itt->positions.begin(); ittt != itt->positions.end(); ittt++){
//					cout << "\t\t\t unsigned short: " << *ittt << endl;
				infoLine += intToStr( *ittt ) + ":";
			}
		}
//			cout << "String Line: " << infoLine << endl;
		miniMapsFile << infoLine << endl;
		infoLine.clear();
	}		
}




void MapsDisk::readSuperMap(){
	
	string file_name = "/work/superMaps/SuperMapsFile_0";
	ifstream miniMapsFile(file_name.c_str());
	cout << "Recuperando Supermapa:  " << file_name << endl;
	string infoLine;
	
	int countIDs = 0;
	
	while(true){
		miniMapsFile >> infoLine;
		if( !miniMapsFile.eof() ){
			
			unsigned long long ID = 0;
			unsigned int vectorIndex = 0;
			unsigned int documentsSize = 0;
			unsigned int PositionVectorId = 0;
			unsigned int positionSize = 0;
			unsigned short int unsignedShort = 0;

			int posA, posB;
			int elementoCont;
			
			elementoCont = 0;
			posA = 0;
			
			PositionVector tempPos;
			WellSizedVector tempWSV;
			
			while(posA < infoLine.size()){
				
				posB = infoLine.find_first_of(":",posA);
				if(posB == string::npos) break;
				
				if(elementoCont == 0){
					stringstream(infoLine.substr(posA, posB-posA)) >> ID;
					cout << "ID: " << ID << endl;
				}
				else if(elementoCont == 1){
					stringstream(infoLine.substr(posA, posB-posA)) >> vectorIndex;
					cout << "\tvectorIndex: " << vectorIndex << endl;
					tempWSV.vectorIndex = vectorIndex;
					tempWSV.initializeVector();
				}
				else if(elementoCont == 2){
					stringstream(infoLine.substr(posA, posB-posA)) >> documentsSize;
					cout << "\tdocumentsSize: " << documentsSize << endl;
				}
				else if(elementoCont == 3){
					stringstream(infoLine.substr(posA, posB-posA)) >> PositionVectorId;
					cout << "\t\tPositionVectorId: " << PositionVectorId << endl;
					tempPos.id = PositionVectorId;
					tempPos.positions.clear();
				}
				else if(elementoCont == 4){
					stringstream(infoLine.substr(posA, posB-posA)) >> positionSize;
					cout << "\t\tpositionSize: " << positionSize << endl;
					tempPos.initializeVector(positionSize);
				}
				else if(elementoCont < 5 +  positionSize){  //pena numShorts
					stringstream(infoLine.substr(posA, posB-posA)) >> unsignedShort;
					cout << "\t\t\tunsignedShort: " << unsignedShort << endl;
					tempPos.insertPosition(unsignedShort);
				}
				else {  // pega mais info dos vetores retornando para PositionVectorId
					elementoCont = 3;
					tempWSV.documents.push_back(tempPos);
					continue;
				}
				posA = posB+1;
				elementoCont++;
			}
			//pega o ultimo
			if(tempPos.positions.size() != 0) tempWSV.documents.push_back(tempPos);
			
			countIDs++;
//			wordDictionary[ID] = tempWSV;
			
//			cout << "ID: " << ID << endl;
//			cout << "\tvectorIndex: " << vectorIndex << endl;
//			cout << "\tdocumentsSize: " << documentsSize << endl;
//			cout << "\t\tPositionVectorId: " << PositionVectorId << endl;
//			cout << "\t\tpositionSize: " << positionSize << endl; 
//			cout << "\t\t\tunsignedShort: " << unsignedShort << endl; 
			
		}else break;
		
//		cout << "Total de IDs: " << countIDs << endl;
	}
}


void MapsDisk::DecodeString(WellSizedVector &_wsv, unsigned long long &_id, string _line, unsigned long & _allBytesWSV){

	
	unsigned long long ID = 0;
	unsigned int vectorIndex = 0;
	unsigned int documentsSize = 0;
	unsigned int PositionVectorId = 0;
	unsigned int firstOccurrence = 0;
	unsigned int positionSize = 0;
	unsigned short int unsignedShort = 0;
	
	_allBytesWSV = 0;
	
	uint posA, posB;
	uint elementoCont;
				
	elementoCont = 0;
	posA = 0;

	PositionVector tempPos;
	WellSizedVector tempWSV;
	string infoLine = _line;
	
	while(posA < infoLine.size()){
		
		posB = infoLine.find_first_of(":",posA);
		if(posB == string::npos) break;
		
		if(elementoCont == 0){
			stringstream(infoLine.substr(posA, posB-posA)) >> hex >> ID;
//			cout << "ID: " << ID << endl;
		}
		else if(elementoCont == 1){
			stringstream(infoLine.substr(posA, posB-posA)) >> hex >> vectorIndex;
//			cout << "\t vectorIndex: " << vectorIndex << endl;
			tempWSV.vectorIndex = vectorIndex;
//			tempWSV.initializeVector();
			_allBytesWSV += 4;
		}
		else if(elementoCont == 2){
			stringstream(infoLine.substr(posA, posB-posA)) >> hex >> documentsSize;
			tempWSV.reserve(documentsSize);
//			cout << "\t documentsSize: " << documentsSize << endl;
		}
		else if(elementoCont == 3){
			stringstream(infoLine.substr(posA, posB-posA)) >> hex >> PositionVectorId;
//			cout << "\t\t PositionVectorId: " << PositionVectorId << endl;
			tempPos.id = PositionVectorId;
			tempPos.positions.clear();
			_allBytesWSV += 4 + 8;  //ID + Vector
		}
		else if(elementoCont == 4){
			stringstream(infoLine.substr(posA, posB-posA)) >> hex >> firstOccurrence;
//			cout << "\t\t firstOccurrence: " << firstOccurrence << endl;
			tempPos.firstOccurrence = firstOccurrence;
			_allBytesWSV += 4;
		}
		else if(elementoCont == 5){
			stringstream(infoLine.substr(posA, posB-posA)) >> hex >> positionSize;
//			cout << "\t\t positionSize: " << positionSize << endl;
			tempPos.initializeVector(positionSize);
			_allBytesWSV += 8;  //Vector de unsignedShort
		}
		else if(elementoCont < 6 +  positionSize){  //pena numShorts
			stringstream(infoLine.substr(posA, posB-posA)) >> hex >> unsignedShort;
//			cout << "\t\t\t unsignedShort: " << unsignedShort << endl;
			tempPos.insertPosition(unsignedShort);
			_allBytesWSV += 2;
		}
		else {  // pega mais info dos vetores retornando para PositionVectorId
			elementoCont = 3;
//			cout << "Pushing" << endl;
			tempWSV.documents.push_back(tempPos);
			continue;
		}
		posA = posB+1;
		elementoCont++;

	}
	//pega o ultimo
	if(tempPos.positions.size() != 0){
		tempWSV.documents.push_back(tempPos);
//		cout << "Pushing" << endl;
	}
	
	if(positionSize == 0){
		tempWSV.documents.push_back(tempPos);
//		cout << "Pushing" << endl;
//		cout << "Deu Zero !!! " << endl;
	}
	
	
	_wsv = tempWSV;
	_id = ID;
	cout << dec;
		
//	cout << "ID: " << ID << endl;
//	cout << "\tvectorIndex: " << vectorIndex << endl;
//	cout << "\tdocumentsSize: " << documentsSize << endl;
//	cout << "\t\tPositionVectorId: " << PositionVectorId << endl;
//	cout << "\t\tpositionSize: " << positionSize << endl; 
//	cout << "\t\t\tunsignedShort: " << unsignedShort << endl; 
	
}

bool MapsDisk::getVector( unsigned long long & wordID, vector<WellSizedVector> & myVector, unsigned long long & incremento){
	
	
	for( int i=0; i< numMinimpas; i++ ){
		if(inAllminiMaps[i].eof()) continue;
		if(checkedMiniMaps[i] == true) continue; //continua se ja viu esse
		checkedMiniMaps[i] = true;
		string teste;
		inAllminiMaps[i] >> teste;
		if(teste.size() == 0){
			checkedMiniMapsEOF[i] = true;
			continue;
		}
//		cout << teste << endl;
		DecodeString( wsvToMerge[i], idToMerge[i], teste, allBytesWSV[i]);
//		cout << "Id da Palavra decodificada: " << idToMerge[i] << endl; 
	}
	
	//determina o Minimo
	unsigned long long minimoID;
	minimoID = ULLONG_MAX; // limits !!!
	
	for(int i=0; i < numMinimpas; i++)
		if(idToMerge[i] < minimoID && !checkedMiniMapsEOF[i]) minimoID = idToMerge[i];
	
	if(minimoID == ULLONG_MAX){
		cout << "AQUI~ !!!!!!!!!!!!!!!!!!!!!!! " << endl;
		cout << "numMinimpas: " << numMinimpas << endl;
		return false;
	}
	
	//monta vetor consumindo todos os minimos....
	myVector.clear();
	wordID = minimoID;
	
	incremento = 0;
	
	for(int i=0; i < numMinimpas; i++){
		if( idToMerge[i] == minimoID && !checkedMiniMapsEOF[i]){
			myVector.push_back(wsvToMerge[i]);
			checkedMiniMaps[i] = false;
			if(inAllminiMaps[i].eof()) checkedMiniMapsEOF[i] = true;
			incremento += allBytesWSV[i];
		}
	}
	
	return true;
}
